package co.com.tye.modelo.control;

import co.com.tye.dataaccess.dao.*;
import co.com.tye.exceptions.*;
import co.com.tye.modelo.*;
import co.com.tye.modelo.dto.GruposOpcionesDTO;
import co.com.tye.modelo.dto.OpcionesDTO;
import co.com.tye.modelo.dto.ProgramaDTO;
import co.com.tye.utilities.Utilities;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * @author Zathura Code Generator http://code.google.com/p/zathura/
 *         www.zathuracode.org
 *
 */
@Scope("singleton")
@Service("ProgramaLogic")
public class ProgramaLogic implements IProgramaLogic {
	/**
	 * DAO injected by Spring that manages Programa entities
	 *
	 */
	@Autowired
	private IProgramaDAO programaDAO;

	/**
	 * DAO injected by Spring that manages DocentePrograma entities
	 *
	 */
	@Autowired
	private IDocenteProgramaDAO docenteProgramaDAO;

	/**
	 * DAO injected by Spring that manages Permisos entities
	 *
	 */
	@Autowired
	private IPermisosDAO permisosDAO;

	/**
	 * DAO injected by Spring that manages Usuario entities
	 *
	 */
	@Autowired
	private IUsuarioDAO usuarioDAO;

	/**
	 * Logic injected by Spring that manages Facultad entities
	 *
	 */
	@Autowired
	IFacultadLogic logicFacultad1;

	@Transactional(readOnly = true)
	public List<Programa> getPrograma() throws Exception {
		List<Programa> list = new ArrayList<Programa>();

		try {
			list = programaDAO.findAll();
		} catch (Exception e) {
			throw new ZMessManager().new GettingException(ZMessManager.ALL
					+ "Programa");
		} finally {
		}

		return list;
	}

	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public void savePrograma(Programa entity) throws Exception {
		try {
			if (entity.getFacultad() == null) {
				throw new ZMessManager().new ForeignException("facultad");
			}

			if ((entity.getEstadoRegistro() != null)
					&& (Utilities.checkWordAndCheckWithlength(
							entity.getEstadoRegistro(), 45) == false)) {
				throw new ZMessManager().new NotValidFormatException(
						"estadoRegistro");
			}

			if (entity.getIdprograma() == null) {
				throw new ZMessManager().new EmptyFieldException("idprograma");
			}

			if (entity.getIsbn() == null) {
				throw new ZMessManager().new EmptyFieldException("isbn");
			}

			if ((entity.getIsbn() != null)
					&& (Utilities.checkWordAndCheckWithlength(entity.getIsbn(),
							45) == false)) {
				throw new ZMessManager().new NotValidFormatException("isbn");
			}

			if (entity.getNombrePrograma() == null) {
				throw new ZMessManager().new EmptyFieldException(
						"nombrePrograma");
			}

			if ((entity.getNombrePrograma() != null)
					&& (Utilities.checkWordAndCheckWithlength(
							entity.getNombrePrograma(), 45) == false)) {
				throw new ZMessManager().new NotValidFormatException(
						"nombrePrograma");
			}

			if ((entity.getUsuarioCreador() != null)
					&& (Utilities.checkWordAndCheckWithlength(
							entity.getUsuarioCreador(), 45) == false)) {
				throw new ZMessManager().new NotValidFormatException(
						"usuarioCreador");
			}

			if ((entity.getUsuarioUltimaModificacion() != null)
					&& (Utilities.checkWordAndCheckWithlength(
							entity.getUsuarioUltimaModificacion(), 45) == false)) {
				throw new ZMessManager().new NotValidFormatException(
						"usuarioUltimaModificacion");
			}

			if (entity.getFacultad().getIdfacultad() == null) {
				throw new ZMessManager().new EmptyFieldException(
						"idfacultad_Facultad");
			}

			if (getPrograma(entity.getIdprograma()) != null) {
				throw new ZMessManager(ZMessManager.ENTITY_WITHSAMEKEY);
			}

			programaDAO.save(entity);
		} catch (Exception e) {
			throw e;
		} finally {
		}
	}

	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public void deletePrograma(Programa entity) throws Exception {
		if (entity == null) {
			throw new ZMessManager().new NullEntityExcepcion("Programa");
		}

		if (entity.getIdprograma() == null) {
			throw new ZMessManager().new EmptyFieldException("idprograma");
		}

		List<DocentePrograma> docenteProgramas = null;
		List<Permisos> permisoses = null;
		List<Usuario> usuarios = null;

		try {
			docenteProgramas = docenteProgramaDAO.findByProperty(
					"programa.idprograma", entity.getIdprograma());

			if (Utilities.validationsList(docenteProgramas) == true) {
				throw new ZMessManager().new DeletingException(
						"docenteProgramas");
			}

			permisoses = permisosDAO.findByProperty("programa.idprograma",
					entity.getIdprograma());

			if (Utilities.validationsList(permisoses) == true) {
				throw new ZMessManager().new DeletingException("permisoses");
			}

			usuarios = usuarioDAO.findByProperty("programa.idprograma",
					entity.getIdprograma());

			if (Utilities.validationsList(usuarios) == true) {
				throw new ZMessManager().new DeletingException("usuarios");
			}

			programaDAO.delete(entity);
		} catch (Exception e) {
			throw e;
		} finally {
		}
	}

	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public void updatePrograma(Programa entity) throws Exception {
		try {
			if (entity == null) {
				throw new ZMessManager().new NullEntityExcepcion("Programa");
			}

			if (entity.getFacultad() == null) {
				throw new ZMessManager().new ForeignException("facultad");
			}

			if ((entity.getEstadoRegistro() != null)
					&& (Utilities.checkWordAndCheckWithlength(
							entity.getEstadoRegistro(), 45) == false)) {
				throw new ZMessManager().new NotValidFormatException(
						"estadoRegistro");
			}

			if (entity.getIdprograma() == null) {
				throw new ZMessManager().new EmptyFieldException("idprograma");
			}

			if (entity.getIsbn() == null) {
				throw new ZMessManager().new EmptyFieldException("isbn");
			}

			if ((entity.getIsbn() != null)
					&& (Utilities.checkWordAndCheckWithlength(entity.getIsbn(),
							45) == false)) {
				throw new ZMessManager().new NotValidFormatException("isbn");
			}

			if (entity.getNombrePrograma() == null) {
				throw new ZMessManager().new EmptyFieldException(
						"nombrePrograma");
			}

			if ((entity.getNombrePrograma() != null)
					&& (Utilities.checkWordAndCheckWithlength(
							entity.getNombrePrograma(), 45) == false)) {
				throw new ZMessManager().new NotValidFormatException(
						"nombrePrograma");
			}

			if ((entity.getUsuarioCreador() != null)
					&& (Utilities.checkWordAndCheckWithlength(
							entity.getUsuarioCreador(), 45) == false)) {
				throw new ZMessManager().new NotValidFormatException(
						"usuarioCreador");
			}

			if ((entity.getUsuarioUltimaModificacion() != null)
					&& (Utilities.checkWordAndCheckWithlength(
							entity.getUsuarioUltimaModificacion(), 45) == false)) {
				throw new ZMessManager().new NotValidFormatException(
						"usuarioUltimaModificacion");
			}

			if (entity.getFacultad().getIdfacultad() == null) {
				throw new ZMessManager().new EmptyFieldException(
						"idfacultad_Facultad");
			}

			programaDAO.update(entity);
		} catch (Exception e) {
			throw e;
		} finally {
		}
	}

	@Transactional(readOnly = true)
	public List<ProgramaDTO> getDataPrograma() throws Exception {
		try {
			List<Programa> programa = programaDAO.findAll();

			List<ProgramaDTO> programaDTO = new ArrayList<ProgramaDTO>();

			for (Programa programaTmp : programa) {
				ProgramaDTO programaDTO2 = new ProgramaDTO();

				programaDTO2.setIdprograma(programaTmp.getIdprograma());
				programaDTO2
						.setEstadoRegistro((programaTmp.getEstadoRegistro() != null) ? programaTmp
								.getEstadoRegistro() : null);
				programaDTO2.setFechaCreacion(programaTmp.getFechaCreacion());
				programaDTO2.setFechaUltimaModificacion(programaTmp
						.getFechaUltimaModificacion());
				programaDTO2
						.setIsbn((programaTmp.getIsbn() != null) ? programaTmp
								.getIsbn() : null);
				programaDTO2
						.setNombrePrograma((programaTmp.getNombrePrograma() != null) ? programaTmp
								.getNombrePrograma() : null);
				programaDTO2
						.setUsuarioCreador((programaTmp.getUsuarioCreador() != null) ? programaTmp
								.getUsuarioCreador() : null);
				programaDTO2.setUsuarioUltimaModificacion((programaTmp
						.getUsuarioUltimaModificacion() != null) ? programaTmp
						.getUsuarioUltimaModificacion() : null);
				programaDTO2.setIdfacultad_Facultad((programaTmp.getFacultad()
						.getIdfacultad() != null) ? programaTmp.getFacultad()
						.getIdfacultad() : null);
				programaDTO2.setFacultadNombre((programaTmp.getFacultad()
						.getNombreFacultad() != null) ? programaTmp
						.getFacultad().getNombreFacultad() : null);

				programaDTO.add(programaDTO2);

			}

			return programaDTO;
		} catch (Exception e) {
			throw e;
		}
	}

	@Transactional(readOnly = true)
	public Programa getPrograma(Integer idprograma) throws Exception {
		Programa entity = null;

		try {
			entity = programaDAO.findById(idprograma);
		} catch (Exception e) {
			throw new ZMessManager().new FindingException("Programa");
		} finally {
		}

		return entity;
	}

	@Transactional(readOnly = true)
	public List<Programa> findPagePrograma(String sortColumnName,
			boolean sortAscending, int startRow, int maxResults)
			throws Exception {
		List<Programa> entity = null;

		try {
			entity = programaDAO.findPage(sortColumnName, sortAscending,
					startRow, maxResults);
		} catch (Exception e) {
			throw new ZMessManager().new FindingException("Programa Count");
		} finally {
		}

		return entity;
	}

	@Transactional(readOnly = true)
	public Long findTotalNumberPrograma() throws Exception {
		Long entity = null;

		try {
			entity = programaDAO.count();
		} catch (Exception e) {
			throw new ZMessManager().new FindingException("Programa Count");
		} finally {
		}

		return entity;
	}

	/**
	 *
	 * @param varibles
	 *            este arreglo debera tener:
	 *
	 *            [0] = String variable = (String) varibles[i]; representa como
	 *            se llama la variable en el pojo
	 *
	 *            [1] = Boolean booVariable = (Boolean) varibles[i + 1];
	 *            representa si el valor necesita o no ''(comillas simples)usado
	 *            para campos de tipo string
	 *
	 *            [2] = Object value = varibles[i + 2]; representa el valor que
	 *            se va a buscar en la BD
	 *
	 *            [3] = String comparator = (String) varibles[i + 3]; representa
	 *            que tipo de busqueda voy a hacer.., ejemplo: where
	 *            nombre=william o where nombre<>william, en este campo iria el
	 *            tipo de comparador que quiero si es = o <>
	 *
	 *            Se itera de 4 en 4..., entonces 4 registros del arreglo
	 *            representan 1 busqueda en un campo, si se ponen mas pues el
	 *            continuara buscando en lo que se le ingresen en los otros 4
	 *
	 *
	 * @param variablesBetween
	 *
	 *            la diferencia son estas dos posiciones
	 *
	 *            [0] = String variable = (String) varibles[j]; la variable ne
	 *            la BD que va a ser buscada en un rango
	 *
	 *            [1] = Object value = varibles[j + 1]; valor 1 para buscar en
	 *            un rango
	 *
	 *            [2] = Object value2 = varibles[j + 2]; valor 2 para buscar en
	 *            un rango ejempolo: a > 1 and a < 5 --> 1 seria value y 5 seria
	 *            value2
	 *
	 *            [3] = String comparator1 = (String) varibles[j + 3];
	 *            comparador 1 ejemplo: a comparator1 1 and a < 5
	 *
	 *            [4] = String comparator2 = (String) varibles[j + 4];
	 *            comparador 2 ejemplo: a comparador1>1 and a comparador2<5 (el
	 *            original: a > 1 and a < 5) *
	 * @param variablesBetweenDates
	 *            (en este caso solo para mysql) [0] = String variable =
	 *            (String) varibles[k]; el nombre de la variable que hace
	 *            referencia a una fecha
	 *
	 *            [1] = Object object1 = varibles[k + 2]; fecha 1 a
	 *            comparar(deben ser dates)
	 *
	 *            [2] = Object object2 = varibles[k + 3]; fecha 2 a
	 *            comparar(deben ser dates)
	 *
	 *            esto hace un between entre las dos fechas.
	 *
	 * @return lista con los objetos que se necesiten
	 * @throws Exception
	 */
	@Transactional(readOnly = true)
	public List<Programa> findByCriteria(Object[] variables,
			Object[] variablesBetween, Object[] variablesBetweenDates)
			throws Exception {
		List<Programa> list = new ArrayList<Programa>();
		String where = new String();
		String tempWhere = new String();

		if (variables != null) {
			for (int i = 0; i < variables.length; i++) {
				if ((variables[i] != null) && (variables[i + 1] != null)
						&& (variables[i + 2] != null)
						&& (variables[i + 3] != null)) {
					String variable = (String) variables[i];
					Boolean booVariable = (Boolean) variables[i + 1];
					Object value = variables[i + 2];
					String comparator = (String) variables[i + 3];

					if (booVariable.booleanValue()) {
						tempWhere = (tempWhere.length() == 0) ? ("(model."
								+ variable + " " + comparator + " \'" + value + "\' )")
								: (tempWhere + " AND (model." + variable + " "
										+ comparator + " \'" + value + "\' )");
					} else {
						tempWhere = (tempWhere.length() == 0) ? ("(model."
								+ variable + " " + comparator + " " + value + " )")
								: (tempWhere + " AND (model." + variable + " "
										+ comparator + " " + value + " )");
					}
				}

				i = i + 3;
			}
		}

		if (variablesBetween != null) {
			for (int j = 0; j < variablesBetween.length; j++) {
				if ((variablesBetween[j] != null)
						&& (variablesBetween[j + 1] != null)
						&& (variablesBetween[j + 2] != null)
						&& (variablesBetween[j + 3] != null)
						&& (variablesBetween[j + 4] != null)) {
					String variable = (String) variablesBetween[j];
					Object value = variablesBetween[j + 1];
					Object value2 = variablesBetween[j + 2];
					String comparator1 = (String) variablesBetween[j + 3];
					String comparator2 = (String) variablesBetween[j + 4];
					tempWhere = (tempWhere.length() == 0) ? ("(" + value + " "
							+ comparator1 + " " + variable + " and " + variable
							+ " " + comparator2 + " " + value2 + " )")
							: (tempWhere + " AND (" + value + " " + comparator1
									+ " " + variable + " and " + variable + " "
									+ comparator2 + " " + value2 + " )");
				}

				j = j + 4;
			}
		}

		if (variablesBetweenDates != null) {
			for (int k = 0; k < variablesBetweenDates.length; k++) {
				if ((variablesBetweenDates[k] != null)
						&& (variablesBetweenDates[k + 1] != null)
						&& (variablesBetweenDates[k + 2] != null)) {
					String variable = (String) variablesBetweenDates[k];
					Object object1 = variablesBetweenDates[k + 1];
					Object object2 = variablesBetweenDates[k + 2];
					String value = null;
					String value2 = null;

					try {
						Date date1 = (Date) object1;
						Date date2 = (Date) object2;
						value = Utilities
								.formatDateWithoutTimeInAStringForBetweenWhere(date1);
						value2 = Utilities
								.formatDateWithoutTimeInAStringForBetweenWhere(date2);
					} catch (Exception e) {
						list = null;
						throw e;
					}

					tempWhere = (tempWhere.length() == 0) ? ("(model."
							+ variable + " between \'" + value + "\' and \'"
							+ value2 + "\')") : (tempWhere + " AND (model."
							+ variable + " between \'" + value + "\' and \'"
							+ value2 + "\')");
				}

				k = k + 2;
			}
		}

		if (tempWhere.length() == 0) {
			where = null;
		} else {
			where = "(" + tempWhere + ")";
		}

		try {
			list = programaDAO.findByCriteria(where);
		} catch (Exception e) {
			throw new Exception(e.getMessage());
		} finally {
		}

		return list;
	}

	@Transactional(readOnly = true)
	public List<GruposOpcionesDTO> consultarNombresGrupos(int codigo)
			throws Exception {
		return programaDAO.consultarNombresGrupos(codigo);
	}

	@Transactional(readOnly = true)
	public List<OpcionesDTO> consultarOpciones(int codigo) throws Exception {
		return programaDAO.consultarOpciones(codigo);
	}

}
